package com.gpframework.common.pay.leshua.service;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gpframework.common.pay.leshua.exception.BizException;
import com.gpframework.common.pay.leshua.req.LeshuaBaseReq;
import com.gpframework.common.pay.leshua.res.LeshuaBaseRes;
import com.gpframework.common.pay.leshua.util.HttpClientHelper;
import com.gpframework.common.pay.leshua.util.LeshuaSignature;
import com.gpframework.common.pay.leshua.util.LeshuaUtils;
/**
 * @author eden
 * @date 2018/5/21 下午3:36
 * @desc
 */
public abstract class LeshuaAbsService<Req extends LeshuaBaseReq, Res extends LeshuaBaseRes> {

	private Logger logger = LoggerFactory.getLogger(getClass());

	HttpClientHelper httpClientHelper = new HttpClientHelper();
	/**
	 * 判断乐刷是否返回通信成功
	 *
	 * @param res
	 * @return
	 */
	public boolean isStatusOK(Res res) {
		return res != null && LeshuaConfigure.SUCCESS_CODE.equals(res.getResp_code());
	}

	/**
	 * 判断乐刷是否返回业务请求成功
	 *
	 * @param res
	 * @return
	 */
	public boolean isBizRequestOK(Res res) {
		return isStatusOK(res) && LeshuaConfigure.SUCCESS_CODE.equals(res.getResult_code());
	}

	/**
	 * 调用乐刷交易接口
	 *
	 * @param reqMap
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public final Res request(Map<String,String> reqMap, String apiKey) throws Exception {
		String respXml = this.request(LeshuaConfigure.JHZF_REQUEST_URL, reqMap, apiKey, true);
		// 将从API返回的XML数据映射到Java对象
		return (Res) LeshuaUtils.getObjectFromXML(respXml, getRespClass(), "leshua");
	}

	/**
	 * 调用乐刷交易接口
	 * @param reqMap
	 * @param apiKey
	 * @param isCheckRespSign 是否对返回参数进行验签
	 * @return
	 * @throws Exception
	 */
	public final String request(Map<String,String> reqMap, String apiKey, boolean isCheckRespSign) throws Exception {
		return this.request(LeshuaConfigure.JHZF_REQUEST_TEST_URL, reqMap, apiKey, isCheckRespSign);
	}

	/**
	 * 调用乐刷接口
	 * @param serviceUrl
	 * @param reqMap
	 * @param apiKey
	 * @param isCheckRespSign
	 * @return
	 * @throws Exception
	 */
	public final String request(String serviceUrl, Map<String,String> reqMap, String apiKey, boolean isCheckRespSign) throws Exception {
		long costTimeStart = System.currentTimeMillis();
		// 根据API给的签名规则进行签名
		String sign = LeshuaSignature.getMD5Sign(reqMap, reqExcludedSignParams(), apiKey);
		reqMap.put("sign", sign);

		String respStr = httpClientHelper.postForm(serviceUrl, reqMap, HttpClientHelper.ACCEPT_TYPE_XML);
		long totalTimeCost = System.currentTimeMillis() - costTimeStart;
		// 打印回包数据
		logger.info("接口：{}，请求耗时：{}ms，请求参数：{}，\n乐刷返回的数据如下：{}", getInterfaceName(), totalTimeCost, reqMap, respStr);

		if (isCheckRespSign) {
			if (respStr.contains("<sign>") && !LeshuaSignature.checkIsSignValidFromResponseString(respStr, resExcludedSignParams(), apiKey)) {
				logger.error("接口：{}，订单号：{}，验签失败，数据可能被篡改了！！！", getInterfaceName(), reqMap.get("third_order_id"));
				throw new BizException("验签失败");
			}
		}
		return respStr;
	}

	/**
	 * 获取乐刷响应错误信息
	 * @param res
	 * @param defaultErrMsg
	 * @return
	 */
	public String getErrMsg(Res res, String defaultErrMsg) {
		String errMsg = defaultErrMsg;
		if (StringUtils.isNotEmpty(res.getResp_msg())) {
			errMsg = res.getResp_msg();
		}
		if (StringUtils.isNotEmpty(res.getError_msg())) {
			errMsg = res.getError_msg();
		}
		return errMsg;
	}

	/**
	 * 返回接口名称
	 *
	 * @return
	 */
	protected abstract String getInterfaceName();

	/**
	 * 返回响应class
	 *
	 * @return
	 */
	protected abstract Class<Res> getRespClass();

	/**
	 *
	 * 请求参数不参与计算签名的参数
	 * @return
	 */
	protected Set<String> reqExcludedSignParams() {
		Set<String> exludedSignParams = new HashSet<String>(1);
		exludedSignParams.add("sign");
		return exludedSignParams;
	}

	/**
	 *
	 * 响应结果不参与计算签名的参数
	 * @return
	 */
	protected Set<String> resExcludedSignParams() {
		Set<String> exludedSignParams = new HashSet<String>(2);
		exludedSignParams.add("sign");
		exludedSignParams.add("resp_code");
		return exludedSignParams;
	}

}
